package com.sjgs.gis.common;

import com.sjgs.common.utils.KryoUtils;
import com.sjgs.gis.domain.ScheduleJob;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import static com.sjgs.common.Constants.PARAMS_SEPARATOR;

public class QuartzFactory implements Job {

    private static final Log logger = LogFactory.getLog(QuartzFactory.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        //获取调度数据
        ScheduleJob scheduleJob = (ScheduleJob) jobExecutionContext.getMergedJobDataMap().get("scheduleJob");
        //获取对应的Bean
        Object object = ApplicationContextHolder.getBean(scheduleJob.getBeanName());
        try {
            Class<?>[] parameterTypes = null;
            //得到方法中的所有参数类型
            if (scheduleJob.getParameterTypes() != null) {
                String[] parameterClazzStr = scheduleJob.getParameterTypes().split(PARAMS_SEPARATOR);
                parameterTypes = new Class<?>[parameterClazzStr.length];
                for (int i = 0; i < parameterClazzStr.length; i++) {
                    parameterTypes[i] = Class.forName(parameterClazzStr[i]);
                }
            }
            //利用反射执行对应方法
            Method method = parameterTypes == null ? object.getClass().getMethod(scheduleJob.getMethodName()) : object.getClass().getMethod(scheduleJob.getMethodName(), parameterTypes);
            List<Object> listValue = new ArrayList<Object>();
            if (scheduleJob.getParameters() != null) {
                //简单参数类型，没有rpc反序列化过程不能是对象
                List<Object> params = Arrays.asList(scheduleJob.getParameters().split(PARAMS_SEPARATOR));
                //循环参数类型
                for (int i = 0; i < parameterTypes.length; i++) {
                    if (params.size() > i) {
                        if (Objects.nonNull(params.get(i))) {
                            listValue.addAll(getValueList(parameterTypes[i], params.get(i)));
                        } else {
                            listValue.add(null);
                        }
                    } else {
                        listValue.add(null);
                    }
                }
            }
            if (listValue.size() > 0) {
                //带参数调用方法
                method.invoke(object, listValue.toArray());
            } else {
                //不带参数调用方法
                method.invoke(object);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    private static List<Object> getValueList(Class<?> parameter, Object value) {
        List<Object> list = new ArrayList<Object>();
        if ("java.lang.String".equals(parameter.getTypeName())) {
            list.add(value);
        } else if ("java.lang.Character".equals(parameter.getTypeName())) {
            char[] ch = ((String) value).toCharArray();
            list.add(ch[0]);
        } else if ("char".equals(parameter.getTypeName())) {
            char[] ch = ((String) value).toCharArray();
            list.add(ch[0]);
        } else if ("java.lang.Double".equals(parameter.getTypeName())) {
            list.add(Double.parseDouble((String) value));
        } else if ("double".equals(parameter.getTypeName())) {
            list.add(Double.parseDouble((String) value));
        } else if ("java.lang.Integer".equals(parameter.getTypeName())) {
            list.add(Integer.parseInt((String) value));
        } else if ("int".equals(parameter.getTypeName())) {
            list.add(Integer.parseInt((String) value));
        } else if ("java.lang.Long".equals(parameter.getTypeName())) {
            list.add(Long.parseLong((String) value));
        } else if ("long".equals(parameter.getTypeName())) {
            list.add(Long.parseLong((String) value));
        } else if ("java.lang.Float".equals(parameter.getTypeName())) {
            list.add(Float.parseFloat((String) value));
        } else if ("float".equals(parameter.getTypeName())) {
            list.add(Float.parseFloat((String) value));
        } else if ("java.lang.Short".equals(parameter.getTypeName())) {
            list.add(Short.parseShort((String) value));
        } else if ("short".equals(parameter.getTypeName())) {
            list.add(Short.parseShort((String) value));
        } else if ("java.lang.Byte".equals(parameter.getTypeName())) {
            list.add(Byte.parseByte((String) value));
        } else if ("byte".equals(parameter.getTypeName())) {
            list.add(Byte.parseByte((String) value));
        } else if ("java.lang.Boolean".equals(parameter.getTypeName())) {
            if ("false".equals(value) || "0".equals(value)) {
                list.add(false);
            } else if ("true".equals(value) || "1".equals(value)) {
                list.add(true);
            }
        } else if ("boolean".equals(parameter.getTypeName())) {
            if ("false".equals(value) || "0".equals(value)) {
                list.add(false);
            } else if ("true".equals(value) || "1".equals(value)) {
                list.add(true);
            }
        } else {
            //对象类型需要反序列化
            list.add(KryoUtils.deserializeObject(Base64.decodeBase64(value.toString()), parameter));
        }
        return list;
    }
}